#!/usr/bin/python
# -*- coding: utf-8 -*-

MSG_PPPOE = {
    "en": "PPPOE",
    "tr": "PPPOE",
}

MSG_DHCP_FAILED = {
    "en": "Unable to get address.",
    "tr": "Adres alınamadı.",
}

"""MSG_NO_SUPPLICANT = {
    "en": "WPA supplicant not found.",
    "tr": "WPA supplicant bulunamadı.",
}

MSG_NO_SUPPLICANT_SERVICE = {
    "en": "Unable to start WPA supplicant service.",
    "tr": "WPA servisi başlatılamadı.",
}

MSG_WPA_FAILED = {
    "en": "Authentication failed.",
    "tr": "Kimlik doğrulama başarısız.",
}
"""

# Add custom messages for pppoe.

import os
from pardus import netutils, iniutils

def listProfiles():
    db = iniutils.iniDB(os.path.join("/etc/network-link", script()))
    return db.listDB()

class Profile:
    def __init__(self, name):
        self.name = name
        self.db = iniutils.iniDB(os.path.join("/etc/network-link", script()))
        self.info = self.db.getDB(self.name)

    def delete(self):
        self.db.remDB(self.name)

    def save(self, no_notify=False):
        is_new = self.name not in listProfiles()
        self.db.setDB(self.name, self.info)
        if no_notify:
            return
        if is_new:
            notify("Network.Link", "connectionChanged", ("added", self.name))
        else:
            notify("Network.Link", "connectionChanged", ("changed", self.name))


def stopSameDevice(name):
    # Additionally:
    os.system("pppoe-stop")
    # Original Code:
    profile = Profile(name)
    device = profile.info["device"]
    for pn in listProfiles():
        if pn == name:
            continue
        pro = Profile(pn)
        if pro.info["device"] == device:
            setState(pn, "down")


def registerNameServers(profile, iface):
    name_mode = profile.info.get("name_mode", "default")
    name_servers = []
    name_domain = ""
    if name_mode == "auto":
        for server in iface.autoNameServers():
            name_servers.append(server)
        name_domain = iface.autoNameSearch()
    elif name_mode == "custom":
        for server in profile.info.get("name_server", ",").split():
           if server.strip():
               name_servers.append(server.strip())
    elif name_mode == "default":
        name_servers = call("dnsmasq", "Network.Stack", "getNameServers")
    call("dnsmasq", "Network.Stack", "registerNameServers", (iface.name, name_servers, name_domain))

def unregisterNameServers(iface):
    call("dnsmasq", "Network.Stack", "unregisterNameServers", (iface.name, [], ""))

# Network.Link methods

def linkInfo():
    d = {
        "type": "pppoe",
        "name": _(MSG_PPPOE),
        "modes": "device,auto,auth",
        #"modes": "device,device_mode,remote,remote_scan,net,auto,auth", #?????
    }
    return d

def authMethods():
    return [
        ("login", "Login/Password"), # TODO: Localize 2. element
    ]

def authParameters(mode):
    return [
        ("username", "Username", "text"), # TODO: Localize 2. element
        ("password", "Password", "pass"), # TODO: Localize 2. element
    ]

def remoteName():
    # TODO: Raise an exception here. "remote" mode not supported
    return ""

def deviceModes():
    # TODO: Raise an exception here. "device_mode" mode not supported
    return []

def deviceList():
    iflist = {}
    for ifc in netutils.interfaces():
        if ifc.isEthernet() and not ifc.isWireless():
            uid = ifc.deviceUID()
            info = netutils.deviceName(uid)
            iflist[uid] = info
    return iflist

def scanRemote(device):
    # TODO: Raise an exception here. "remote_scan" mode not supported
    return []

def setDevice(name, device):
    profile = Profile(name)
    profile.info["device"] = device
    profile.save()

def setDeviceMode(name, mode):
    # TODO: Raise an exception here. No device mode.
    return []

def deleteConnection(name):
    profile = Profile(name)
    profile.delete()
    notify("Network.Link", "connectionChanged", ("deleted", name))

def setAddress(name, mode, address, mask, gateway):
    profile = Profile(name)
    profile.info["net_mode"] = mode
    profile.info["net_address"] = address
    profile.info["net_mask"] = mask
    profile.info["net_gateway"] = gateway
    profile.save()

def setRemote(name, remote):
    # TODO: Raise an exception here. "remote" mode not supported
    pass

def setNameService(name, namemode, nameserver):
    profile = Profile(name)
    profile.info["name_mode"] = namemode
    profile.info["name_server"] = nameserver
    profile.save()

def setAuthMethod(name, method):
    profile = Profile(name)
    profile.info["auth"] = method
    profile.save()

def setAuthParameters(name, key, value):
    profile = Profile(name)
    profile.info["auth_%s" % key] = value
    profile.save()

def getAuthMethod(name):
    profile = Profile(name)
    return profile.info.get("auth", "")

def getAuthParameters(name):
    profile = Profile(name)
    d = {}
    for key in profile.info:
        if key.startswith("auth_"):
            d[key[5:]] = profile.info[key]
    return d

def getState(name):
    profile = Profile(name)
    return profile.info.get("state", "down")

def setState(name, state):
    profile = Profile(name)
    iface = netutils.findInterface(profile.info["device"])
    if state == "up":
        # Stop other profiles on same device
        stopSameDevice(name)
        # Notify clients
        notify("Network.Link", "stateChanged", (name, "connecting", ""))
        # Save state to profile database
        profile.info["state"] = "connecting"
        profile.save(no_notify=True)
        if profile.info.get("net_mode", "auto") == "auto":
            # Start DHCP client
            ret = iface.startAuto()
            if ret == 0 and iface.isUp() and iface.getAddress():
                address = iface.getAddress()
                # Set nameservers
                registerNameServers(profile, iface)
                # Save state to profile database
                profile.info["state"] = "up " + address[0]
                profile.save(no_notify=True)
                # Notify clients
                notify("Network.Link", "stateChanged", (name, "up", address[0]))
            else:
                iface.down()
                # Save state to profile database
                profile.info["state"] = "down"
                profile.save(no_notify=True)
                # Notify clients
                notify("Network.Link", "stateChanged", (name, "inaccesible", _(MSG_DHCP_FAILED)))
        else:
	    pass
	    # We don't have a manual settings option.
	    """
            try:
                net_address = profile.info["net_address"]
                net_mask = profile.info["net_mask"]
                net_gateway = profile.info["net_gateway"]
            except KeyError:
                return
            # Set address
            iface.setAddress(net_address, net_mask)
            iface.up()
            # Set default gateway
            route = netutils.Route()
            route.setDefault(net_gateway)
            # Set nameservers
            registerNameServers(profile, iface)
            # Save state to profile database
            profile.info["state"] = "up " + net_address
            profile.save(no_notify=True)
            # Notify clients
            notify("Network.Link", "stateChanged", (name, "up", net_address))
	    """
    elif state == "down":
        if profile.info.get("net_mode", "auto") == "auto":
            iface.stopAuto()
        iface.down()
        # Reset Network Stack
        unregisterNameServers(iface)
        # Save state to profile database
        profile.info["state"] = "down"
        profile.save(no_notify=True)
        # Notify clients
        notify("Network.Link", "stateChanged", (name, "down", ""))


def connections():
    return listProfiles()

def connectionInfo(name):
    profile = Profile(name)
    device = profile.info["device"]
    return {
        "name": name,
        "device_id": device,
        "device_name": netutils.deviceName(device),
        "net_mode": profile.info.get("net_mode", "auto"),
        "net_address": profile.info.get("net_address", ""),
        "net_mask": profile.info.get("net_mask", ""),
        "net_gateway": profile.info.get("net_gateway", ""),
        "name_mode": profile.info.get("name_mode", "default"),
        "name_server": profile.info.get("name_server", ""),
        "state": profile.info.get("state", "down"),
    }

def kernelEvent(data):
    # TODO: Handle UDEV event
    pass
